<template>
  <div class="cm-editor">
    <codemirror
      ref="cmEditor"
      v-model="value"
      :options="options"
      @input="valueChange"
    />
  </div>
</template>

<script>
// sql-formatter 官网： https://www.npmjs.com/package/sql-formatter
// SQL格式化插件 需要 npm install sql-formatter --save 当前版本 => "sql-formatter": "^4.0.2"
import { format } from 'sql-formatter'

// codemirror 官网： https://codemirror.net
// vue-codemirror 官网： https://www.npmjs.com/package/vue-codemirror
// mount with component 需要 npm install vue-codemirror --save 当前版本 => "vue-codemirror": "^4.0.6"
import { codemirror } from 'vue-codemirror'

// import base style
import 'codemirror/lib/codemirror.css'

// 引入主题后还需要指定 options.theme 为相应主题
import 'codemirror/theme/neo.css'
import 'codemirror/theme/blackboard.css'
import 'codemirror/theme/cobalt.css'

// 第一次初始化时自动刷新编辑器
import 'codemirror/addon/display/autorefresh.js'

// 当前行背景高亮
import 'codemirror/addon/selection/active-line.js'

// 全屏模式
import 'codemirror/addon/display/fullscreen.css'
import 'codemirror/addon/display/fullscreen.js'

// 引入 keymap 使用 sublime 快捷键
import 'codemirror/addon/comment/comment'
import 'codemirror/keymap/sublime'

// 自动补全
import 'codemirror/addon/hint/show-hint.css'
import 'codemirror/addon/hint/show-hint.js'

// 需要引入具体的语法高亮库才会有对应的语法高亮效果
// mode: 'text/x-sh'
import 'codemirror/mode/shell/shell.js'

// mode: 'text/x-sql'
import 'codemirror/mode/sql/sql.js'

// SQL关键字提示
import 'codemirror/addon/hint/sql-hint.js'

// 括号匹配
import 'codemirror/addon/edit/matchbrackets.js'
import 'codemirror/addon/edit/matchtags.js'

// 代码折叠
import 'codemirror/addon/fold/foldgutter.css'
import 'codemirror/addon/fold/foldcode.js'
import 'codemirror/addon/fold/foldgutter.js'

// import more codemirror resource...

export default {
  name: 'CmEditor',
  components: { codemirror },
  props: {},
  data() {
    return {
      // 与 codemirror 编辑器双向绑定的 value
      value: '',

      // 默认配置
      options: {
        // 主题 对应主题库 JS 需要提前引入 白：neo 黑：blackboard 深蓝：cobalt
        theme: 'blackboard',
        // 使用 sublime 快捷键
        keyMap: 'sublime',
        // 默认的语法类型 text/x-sh
        mode: 'text/x-sh',
        // 只读模式
        readOnly: false,
        // 缩进格式
        tabSize: 4,
        // 显示行号
        lineNumbers: true,
        // 第一次初始化时默认 250ms 后自动刷新编辑器
        autoRefresh: { delay: 10 },
        // 当前行背景高亮
        styleActiveLine: true,
        // 光标高度
        cursorHeight: 0.85,
        // 自动获取焦点
        autofocus: false,
        // 括号匹配
        matchBrackets: true,
        // 自动换行
        lineWrapping: true,
        // 代码折叠
        foldGutter: true,
        // 快捷键绑定
        extraKeys: {
          // F10快捷键 全屏/退出全屏
          'F10': function(cm) {
            cm.setOption('fullScreen', !cm.getOption('fullScreen'))
          },
          // Esc快捷键 退出全屏
          'Esc': function(cm) {
            if (cm.getOption('fullScreen')) cm.setOption('fullScreen', false)
          }
          // Tab快捷键 关键字提示并补全
          // 'Tab': 'autocomplete'
        },
        // 自定义提示选项 异步请求时：this._codemirror.setOption('hintOptions', data)
        hintOptions: {
          // 当提示匹配只有一项的时候是否自动补全
          completeSingle: false,
          // 预设自定义提示数据
          tables: {
            table1: ['filed1', 'filed2', 'filed3'],
            table2: ['filed1', 'filed2', 'filed3'],
            table3: ['filed1', 'filed2', 'filed3']
          }
        }
      }
    }
  },
  computed: {
    // codemirror对象
    _codemirror() {
      return this.$refs.cmEditor.codemirror
    }
  },
  watch: {},
  mounted() {
    this.$nextTick(() => {
      // 在 CSS 完成过渡后触发
      window.addEventListener('transitionend', this.init, false)
    })
  },
  beforeDestroy() {
    // 销毁 transitionend 事件
    window.removeEventListener('transitionend', this.init, false)
  },
  methods: {
    // 初始化
    init() {
      this.$nextTick(() => {
        // 将自动提示绑定 change 事件
        this._codemirror.on('change', (cm, event) => {
          // 自动补全、粘贴、赋值事件 以及空格、换行 都会触发 change 事件
          if (event.origin !== 'complete' &&
              event.origin !== 'paste' &&
              event.origin !== 'setValue' &&
              /\w|\./g.test(event.text[0])
          ) {
            cm.showHint()
          }
        })
      })
    },

    // 编辑器 value 改变时触发
    valueChange(newValue) {},

    // 光标定位到 value 最后
    cursorToEnd() {
      this.$nextTick(() => {
        this._codemirror.focus()
        this._codemirror.setCursor(this._codemirror.lineCount(), 0)
      })
    },

    // SQL格式化
    formatSql() {
      this._codemirror.setValue(format(this.value))
    }
  }
}
</script>

<style lang="scss">
    @import './index.scss';
</style>
